<?php
/**
 *
 * User:xinhuazhang
 * Date:2024/5/7
 * TIPS:功能说明
 * Email:<1655626823@qq.com>
 */

namespace app\api\controller;

use app\admin\model\Config;
use app\admin\model\Houses as HousesModel;
use app\common\controller\Frontend;
use app\common\model\Category;
use app\common\model\Tags;
use app\common\model\UserCollect;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Xls;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use think\exception\ValidateException;
use think\facade\App;
use think\facade\Db;

#[Apidoc\Title("房源管理")]
class Houses extends Frontend
{
    protected array $noNeedLogin = ['detail'];
    protected array $noNeedPermission = ['*'];

    #[
        Apidoc\Title("我发布的房源列表"),
        Apidoc\Tag("status 0 => '下架', 1 => '上架'"),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/index"),
        Apidoc\Query(name: "page", type: "number", require: false, desc: "页码", mock: "1"),
        Apidoc\Returned("id", type: "int", desc: "Id"),
    ]
    public function index()
    {
        $page = input('page', 1);
        $where = [];
        //$where[] = ['status', '=', 1];
        $where[] = ['user_id', '=', $this->auth->id];
        $list = HousesModel::where($where)
            ->order('id', 'desc')
            ->paginate()->each(function ($item) {
                $order_row = (new \app\common\model\Orders())->order('id', 'desc')->where([
                    'house_id' => $item['id'],
                    'user_id' => $this->auth->id,
                    'house_type' => 'houses'
                ])->find();
                $item['pay_status'] = $order_row ? $order_row['pay_status'] : 0;//支付状态:0=待支付,1=支付成功,2=已退款
                if ($order_row) {
                    $item['payed_day'] = (time() - $order_row['paid_time']) / (3600 * 24);
                } else {
                    $item['payed_day'] = 0;
                }
                $item['dealer_info'] = '';
                if ($item['status'] == 4) {
                    $dealer_id = (new \app\admin\model\Orders())
                        ->where('id', $item['order_id'])
//                ->where([
//                    'house_id' => $result['id'],
//                    'pay_status' => ['in', [1,3]],
//                    'house_type' => 'findstore'
//                ])
                        ->value('to_uid');
                    $item['dealer_info'] = (new \app\admin\model\User())->where(['id' => $dealer_id])->find();
                }
            });
        $this->success('获取成功', $list);
    }

    #[
        Apidoc\Title("添加单个房源 新版本3.0"),

        Apidoc\Query(name: "industry_pid", type: "number", require: false, desc: "一级行业", mock: "1"),
        Apidoc\Query(name: "industry", type: "数组", require: false, desc: "二级行业", mock: "1"),
        Apidoc\Tag("name	名称
        is_vip 是否是vip  0否1是
        view_price单次查看价格
category_id	房源类型
city	城市选择
introduction	介绍
address	详情地址
acreage	面积
rent_money	租金
user_ids	发布人
has_bounty	是否悬赏:0=否,1=是
reward	悬赏金额
weigh	权重
image	主图（列表）
images	图册
files	视频
status 0 => '下架', 1 => '上架' 2 => '待审核', 3 => '已驳回'
create_time	创建时间
rent_free	免租期月
start_rent	起租 几个月
paymethod	支付方式:1=押一付一,3=押一付三,10=押一付十,6=半年付,12=年付
longitude	经度
latitude	纬度
industry	行业
surround	周边配套
property	物业,
other_tags 标签
prorease_period 预租期
rent_unit 租金单位:0=元/月,1=元/㎡/月,2=元/年    'contact_phone' => '联系电话',"
        ),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/add"),
        Apidoc\Returned("id", type: "int", desc: "Id返回房源id 用于支付佣金"),

    ]
    public function add()
    {
        $data = $this->request->post();
        $data['user_id'] = $this->auth->id;
        $data['status'] = 2;
        $data['create_time'] = time();
        $data['source'] = 1;
        $data['name'] = '房源';
        $filed_config = (new Config())->where(['id' => 17])->find();
        $checked_fields = json_decode($filed_config['value'], true);
        $checked_fields = $checked_fields ? $checked_fields : [];
        $rules = [];
        foreach ($checked_fields as $k => $v) {
            $rules[$v] = 'require';
        }
        $validate = \think\facade\Validate::rule($rules, [
            'name' => '房源公告标题',
            'category_ids' => '房源类型',
            'city' => '城市选择',
            'introduction' => '房源详情',
            'address' => '详情地址',
            'acreage' => '面积',
            'rent_money' => '租金',
            'user_id' => '发布人',
            'has_bounty' => '是否悬赏',
            'reward' => '悬赏金额',
            'weigh' => '权重',
            'image' => '主图（列表）',
            'images' => '图册',
            'files' => '视频',
            'status' => '状态',
            'rent_free' => '免租期月',
            'start_rent' => '起租 几个月',
            'paymethod' => '支付方式',
            'longitude' => '经度',
            'latitude' => '纬度',
            'industry' => '行业',
            'surround' => '周边配套',
            'property' => '物业',
            'seal_status' => '出售状态',
            'other_tags' => '其它标签',
            'rent_unit' => '租金单位',
            'seach_area' => '地区最后一个id',
            'online_time' => '上架时间',
            'down_time' => '下架时间',
            'prorease_period' => '预租期',
            'contact_phone' => '联系电话',
        ]);
        if (!$validate->check($data)) {
            $this->error($validate->getError());
        }

        if (is_numeric($data['city'])) {
            $city = $data['city'];
            $city_2 = Db::name('area')->where('id', $data['city'])->find();
            if ($city_2) {
                $city = $city_2['id'] . ',' . $data['city'];
                $city_3 = Db::name('area')->where('id', $city_2['pid'])->find();
                if ($city_3) {
                    $city = $city;
                }
            }
            $data['city'] = $city;
        }
        $result = HousesModel::create($data);
        if ($result) {
            $role_type = \app\common\model\User::where('id', $this->auth->id)->value('role_type');
            if (!empty($role_type)) {
                $role_type = explode(',', $role_type);
                if (!in_array(1, $role_type)) {
                    $role_type[] = 1;
                } else {
                    $role_type = '';
                }
            } else {
                $role_type = [1];
            }
            if ($role_type) {
                (new \app\admin\model\User())
                    ->where('id', $this->auth->id)
                    ->update([
                        'role_type' => implode(',', $role_type)
                    ]);
            }
            $this->success('发布成功', ['id' => $result->id]);
        } else {
            $this->error('发布失败');
        }
    }

    #[
        Apidoc\Title("编辑单个房源（上下架）"),
        Apidoc\Tag("传单个字段状态status:0=下架,1=上架"),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/edit"),
        Apidoc\Returned("id", type: "int", desc: "Id"),
    ]
    public function edit()
    {
        $data = $this->request->post();
        $id = isset($data['id']) ? $data['id'] : 0;
        if (empty($id)) {
            $this->error('房源id不能为空');
        }
        $result = HousesModel::where(['id' => $id, 'user_id' => $this->auth->id])->find();
        if (!$result) {
            $this->error('房源不存在');
        }
        // 上下架操作
        if (!isset($data['status']) && !isset($data['name'])) {
            //0 => '已下架', 1 => '已上架', 2 => '待审核', 3 => '已驳回'
            $up_status = $result['status'] == 1 ? 0 : 2;
            $result->save([
                'status' => $up_status
            ]);
            $this->success($up_status == 0 ? '下架成功' : '等待审核');
        }
        if ($result['status'] == 1) {
            $this->error('已上架的商品无法进行编辑，请先下架');
        }
        $filed_config = (new Config())->where(['id' => 17])->find();
        $checked_fields = json_decode($filed_config['value'], true);
        $checked_fields = $checked_fields ? $checked_fields : [];
        $rules = [];
        foreach ($checked_fields as $k => $v) {
            $rules[$v] = 'require';
        }
        $validate = \think\facade\Validate::rule($rules, [
            'name' => '房源公告标题',
            'category_ids' => '房源类型',
            'city' => '城市选择',
            'introduction' => '介绍',
            'address' => '详情地址',
            'acreage' => '面积',
            'rent_money' => '租金',
            'user_id' => '发布人',
            'has_bounty' => '是否悬赏',
            'reward' => '悬赏金额',
            'weigh' => '权重',
            'image' => '主图（列表）',
            'images' => '图册',
            'files' => '视频',
            'status' => '状态',
            'rent_free' => '免租期月',
            'start_rent' => '起租 几个月',
            'paymethod' => '支付方式',
            'longitude' => '经度',
            'latitude' => '纬度',
            'industry' => '行业',
            'surround' => '周边配套',
            'property' => '物业',
            'seal_status' => '出售状态',
            'other_tags' => '其它标签',
            'rent_unit' => '租金单位',
            'seach_area' => '地区最后一个id',
            'online_time' => '上架时间',
            'down_time' => '下架时间',
            'prorease_period' => '预租期',   'contact_phone' => '联系电话',
        ]);
        if (!$validate->check($data)) {
            $this->error($validate->getError());
        }
        unset($data['status']);
        unset($data['id']);
        $data['status'] = 2;
        if (is_numeric($data['city'])) {
            $name_are = '';
            $city = $data['city'];
            $city_2 = Db::name('area')->where('id', $data['city'])->find();//本级别信息
            if ($city_2) {
                $name_are = $city_2['name'];
                $city = $city_2['id'] . ',' . $data['city'];
                $city_3 = Db::name('area')->where('id', $city_2['pid'])->find();//上级信息
                if ($city_3) {
                    $name_are = $city_3['name'] . $name_are;

                    $city_4 = Db::name('area')->where('id', $city_3['pid'])->find();//上级信息
                    if ($city_4) {
                        $name_are = $city_4['name'] . $name_are;
                    }
                    $city = $city_3['id'] . $city;
                }
            }
            $data['city'] = $city;
            $data['address'] = str_replace($name_are, '', $data['address']);
        }
        $result = HousesModel::update($data, ['id' => $id]);
        if ($result) {
            $this->success('修改成功');
        } else {
            $this->error('修改失败');
        }
    }

    #[
        Apidoc\Title("房源详情"),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/detail"),
        Apidoc\Returned("id", type: "int", desc: "Id"),
        Apidoc\Returned("pay_status", type: "int", desc: "支付状态"),
        Apidoc\Returned("pay_status_text", type: "string", desc: "支付状态:0=待支付,1=支付成功,2=已退款 3佣金已支付"),
        Apidoc\Returned("payed_day", type: "支付天数", desc: "默认0"),
    ]
    public function detail()
    {
        $id = $this->request->get('id');
        $result = HousesModel::where(['id' => $id, 'user_id' => $this->auth->id])->find();
        $order_row = (new \app\common\model\Orders())->order('id', 'desc')->where([
            'house_id' => $id,
            'user_id' => $this->auth->id,
            'house_type' => 'houses'
        ])->find();
        $result['pay_status'] = $order_row ? $order_row['pay_status'] : 0;////支付状态:0=待支付,1=支付成功,2=已退款 3已付款佣金

        if ($order_row) {
            $result['payed_day'] = (time() - $order_row['paid_time']) / (3600 * 24);
        } else {
            $result['payed_day'] = 0;
        }
        $result['dealer_info'] = '';
        if ($result['status'] == 4) {
            $dealer_id = (new \app\admin\model\Orders())
                ->where('id', $result['order_id'])
//                ->where([
//                    'house_id' => $result['id'],
//                    'pay_status' => 1,
//                    'house_type' => 'houses'
//                ])
                ->value('to_uid');
            $result['dealer_info'] = (new \app\admin\model\User())->where(['id' => $dealer_id])->find();
        }
        if ($result) {
            $this->success('获取成功', $result);
        } else {
            $this->error('获取失败');
        }
    }

    #[
        Apidoc\Title("房源删除"),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/delete"),
        Apidoc\Returned("id", type: "int", desc: "Id"),
    ]
    public function delete()
    {
        $id = $this->request->post('id');
        Db::startTrans();
        $result = HousesModel::where(['id' => $id, 'user_id' => $this->auth->id])
            ->delete();
        (new UserCollect())
            ->where([
                'type' => 'house',
                'houses_id' => $id
            ])->delete();
        Db::commit();
        if ($result) {
            $this->success('删除成功');
        } else {
            $this->error('删除失败');
        }
    }

    #[
        Apidoc\Title("导入房源"),
        Apidoc\Method("POST"),
        Apidoc\Url("/api/Houses/import"),
        Apidoc\Param(name: "file", type: "string", require: true, desc: "上传文件路径", mock: "/templates/houses_template.xlsx"),
        Apidoc\Returned("id", type: "int", desc: "Id"),
    ]
    public function import(): void
    {
        set_time_limit(0);
        ob_clean();
        $file = $this->request->param('file');
        if (empty($file)) {
            $this->error('请选择上传的文件', $this->request->param());
        }
        $ext = pathinfo($file, PATHINFO_EXTENSION);//后缀
        if (!in_array($ext, ['xls', 'xlsx'])) {
            $this->error('不支持此类型文件');
        }
        if ($ext === 'xls') {
            $reader = new Xls();
        } else {
            $reader = new Xlsx();
        }
        $filePath = App::getRootPath() . 'public/' . $file;
        $data = [];
        $reader->setReadDataOnly(TRUE);
        $spreadsheet = $reader->load($filePath);
        $sheet = $spreadsheet->getActiveSheet();
        $highestRow = $sheet->getHighestRow();
        $allColumn = $sheet->getHighestDataColumn(); //取得最大的列号
        $allRow = $sheet->getHighestRow(); //取得一共有多少行
        $highestColumnIndex = Coordinate::columnIndexFromString($allColumn);//最大列转换成数字
        $fileds = [
            'id',
            'name',
            'category_ids',
            'city',
            'introduction',
            'address',
            'acreage',
            'rent_money',
            'has_bounty',
            'reward',
            'image',
            'images',
            'rent_free',
            'start_rent',
            'paymethod',
            'industry',
            'surround',
            'property',
        ];
        $model = new  HousesModel();
        $field_count = count($fileds);
        for ($row = 2; $row <= $highestRow; $row++) {
            // 构建默认字段数据
            $arr_value = [
                'create_time' => time(),
                'update_time' => time(),
            ];
            for ($col = 1; $col <= $field_count - 1; $col++) {
                // 'A' 对应的ASCII码十进制为 64
                // 将ASCII值转为字符
                $chr = $this->getColumnZimu($col);
                // 列转为数据库字段名
                $key = $fileds[$col] ?? $chr;
                $value = $sheet->getCell($chr . $row)->getValue();
                if (in_array($key, ['image', 'images']) && !empty($value)) {
                    $value = '';
                }
                if ($key == 'category_ids' && !empty($value)) {
                    $value = (new Category())->where('name', $value)->value('id');
                }
                if (in_array($key, ['industry', 'surround', 'property']) && !empty($value)) {
                    $speal_arr = array('；', ';');
                    foreach ($speal_arr as $speal) {
                        $value = str_replace($speal, ',', $value);
                    }
                    $cate_values = explode(',', $value);
                    $cate_ids = (new Tags())->whereIn('string', $cate_values)->column('id');
                    $value = $cate_ids ? implode(',', $cate_ids) : '';
                }
                $value = trim($value);
                // 构建当前行数据
                $arr_value[$key] = $value;
            }
            $arr_value['user_id'] = $this->auth->id;
            $arr_value['status'] = 2;
            $data[] = $arr_value;
        }
        $imageFilePath = App::getRootPath() . 'public/uploads/imgs'; //图片本地存储的路径
        $objRead = IOFactory::createReader('Xlsx');
        $objSpreadsheet = $objRead->load($filePath);
        $objWorksheet = $objSpreadsheet->getSheet(0);
        $images_datas = [];
        foreach ($objWorksheet->getDrawingCollection() as $drawing) {
            list($startColumn, $startRow) = Coordinate::coordinateFromString($drawing->getCoordinates());
            $imageFileName = $drawing->getCoordinates() . mt_rand(1000, 9999);
            switch ($drawing->getExtension()) {
                case 'jpg':
                case 'jpeg':
                    $imageFileName .= '.jpg';
                    $source = imagecreatefromjpeg($drawing->getPath());
                    imagejpeg($source, $imageFilePath . $imageFileName);
                    break;
                case 'gif':
                    $imageFileName .= '.gif';
                    $source = imagecreatefromgif($drawing->getPath());
                    imagegif($source, $imageFilePath . $imageFileName);
                    break;
                case 'png':
                    $imageFileName .= '.png';
                    $source = imagecreatefrompng($drawing->getPath());
                    imagepng($source, $imageFilePath . $imageFileName);
                    break;
            }
            $startColumn = $this->ABC2decimal($startColumn);
            if ($startColumn == 10) {

                $data[$startRow - 2]['image'] = '/uploads/imgs' . $imageFileName;
            }
            if ($startColumn == 11) {
                $data[$startRow - 2]['images'] = '/uploads/imgs' . $imageFileName;
            }
            $images_datas[$startRow - 2][$startColumn] = '/uploads/imgs' . $imageFileName;
        }
        $result = $model->saveAll($data);
        if ($result) {
            $this->success('导入成功' . count($data) . '条数据');
        } else {
            $this->error('导入失败', $data);
        }
    }

    private function getColumnZimu($num)
    {
        if ($num >= 0 && $num < 26) {
            // 如果是 A 到 Z 之间的列，直接返回对应的字母
            return chr(65 + $num);
        } else {
            // 针对 AA、AB、AC ... ZZ 这样的列，使用类似递归的方式计算出对应的字母组合
            $result = '';
            while ($num >= 26) {
                $result .= chr(65 + ($num % 26));
                $num = intval($num / 26) - 1;
            }
            $result .= chr(65 + $num);
            return strrev($result); // 需要反转列名字母组合
        }
    }

    public function ABC2decimal($abc)
    {
        $ten = 0;
        $len = strlen($abc);
        for ($i = 1; $i <= $len; $i++) {
            $char = substr($abc, 0 - $i, 1);//反向获取单个字符
            $int = ord($char);
            $ten += ($int - 65) * pow(26, $i - 1);
        }
        return $ten;
    }

}
